<template>
  <!-- 应用容器 -->
  <div class="app-container">
    <el-row style="margin-bottom: 10px">
      <div style="height: 50px" v-if="useRoleData.isEdit">
        当前角色：
        <h2 style="display: inline-block">{{ useRoleData.roleData?.roleName }}</h2>
      </div>
    </el-row>
    <el-row :gutter="20">
      <el-col :span="4" :xs="24">
        <div class="head-container">
          <!-- 部门名称输入框 -->
          <el-input v-model="deptName" placeholder="请输入部门名称" clearable prefix-icon="Search" style="margin-bottom: 12px" />
        </div>
        <div class="head-container">
          <!-- 目录树 -->
          <el-tree
            class="tree-container"
            :data="treeOptions"
            :props="defaultProps"
            :expand-on-click-node="false"
            :filter-node-method="filterNode"
            ref="tree"
            node-key="id"
            default-expand-all
            highlight-current
            @node-click="handleNodeClick"
            size="large"
          />
        </div>
      </el-col>
      <el-col :span="20" :xs="24">
        <el-row :gutter="10">
          <el-col :span="1.5">
            <!-- 保存按钮 -->
            <el-button class="button-style" type="primary" @click="saveEvent" :disabled="columns.length === 0">保存</el-button>
          </el-col>
          <el-col :span="1.5">
            <!-- 选择当前全部按钮 -->
            <el-button class="button-style" type="success" @click="selectAllEvent" :disabled="columns.length === 0"
              >选择当前全部</el-button
            >
          </el-col>
        </el-row>
        <!-- 表格展示 -->
        <el-table v-loading="loading" :data="tableData" :border="true">
          <el-table-column v-if="showTable" width="200" align="center" prop="menuName" label="名称" />
          <el-table-column
            :width="item.width"
            v-for="(item, index) in columns"
            :key="index"
            align="center"
            :prop="item.prop"
            :label="item.label"
          >
            <template v-slot="scope">
              <el-checkbox v-if="scope.row[item.prop]" v-model="scope.row[item.prop].checked" @change="handleCheck(scope.row)" />
            </template>
          </el-table-column>
        </el-table>
      </el-col>
    </el-row>
  </div>
</template>

<script lang="ts" setup>
import type { DeptItem } from "@/typings";
import { addRoleApi, menuListApi, updateRoleApi, roleMenuTreeSelectApi } from "@/api";
import { ref, onMounted } from "vue";
import router from "@/routers";
import { useRoleDataStore } from "@/stores";
import { ElMessage } from "element-plus";
import { all } from "node_modules/axios/index.cjs";

const roleMap = ref<any[]>([]); // 角色映射数据
const deptName = ref(""); // 部门名称
const treeOptions = ref<any[]>([]); // 目录树选项
const defaultProps = {
  // 目录树的默认属性
  children: "children",
  label: "label",
  value: "id"
};
const filterNode = (value: string, data: any) => {
  // 过滤目录树节点
  if (!value) return true;
  return data.label.includes(value);
};

const showTable = ref(false); // 控制表格显示
const allData = ref([]); // 存储所有数据
// 点击目录树
const handleNodeClick = async (data: any) => {
  try {
    loading.value = true;
    showTable.value = true;
    columns.value = [];
    const list = allData.value.filter((item: any) => item.parentId === data.id);
    const menuMap: any = {};
    list.forEach((val: any) => {
      menuMap[val.menuId] = val.children;
    });
    allData.value.forEach((item: any) => {
      const children = menuMap[item.parentId];
      if (children) {
        children.push(item);
      }
    });

    // 获取表格动态列
    const existingQueries = new Set(columns.value.map((i: any) => i.prop));
    list.forEach((item: any) => {
      if (item.children && item.children.length > 0) {
        item.children.forEach((item2: any) => {
          // 使用集合判断是否已经存在
          if (!existingQueries.has(item2.query)) {
            columns.value.push({
              label: item2.menuName,
              prop: item2.query,
              menuType: item2.menuType,
              menuId: item2.menuId,
              width: 100
            });
            // 添加到集合中
            existingQueries.add(item2.query);
          }
        });
      }
    });
    const newData: any = [];
    list.forEach((item: any) => {
      const obj: any = {
        menuName: item.menuName
      };
      if (item.children && item.children.length > 0) {
        item.children.forEach((child: any) => {
          obj[child.query] = {
            checked: roleMap.value.some((item: any) => item === child.menuId),
            menuId: child.menuId
          };
        });
      }
      newData.push(obj);
    });
    tableData.value = newData as any;
  } catch (error) {
    console.error("Error fetching data", error);
  } finally {
    loading.value = false;
  }
};

// 获取菜单列表
const getMenuListApi = async () => {
  const list: any = [];
  try {
    const res = await menuListApi();
    if (res.code === 200) {
      allData.value = res.data;
      res.data.map((item: any) => {
        if (item.parentId === 0) {
          list.push({
            id: item.menuId,
            label: item.menuName,
            children: item.children
          });
        }
      });
      treeOptions.value = list as any;
    }
  } catch (error) {
    console.error("Error fetching data", error);
  }
};

// 初始化
const firstId = ref();
const init = async () => {
  // 初始化方法
  try {
    // 修改
    if (useRoleData.isEdit) {
      const { roleId } = useRoleData.roleData;
      const result = await roleMenuTreeSelectApi(roleId);
      if (result.code === 200) {
        roleMap.value = result.data.checkedKeys;
        menuId.value = result.data.checkedKeys;
      }

      child.value = menuId.value;
      firstId.value = menuId.value;

      let parentObj: any = {};
      // 获取选中按钮权限的所有父节点对象
      allData.value.map((item: any) => {
        menuId.value.forEach((childId: any) => {
          if (item.menuId === childId) {
            parentObj = item;
            return allParentArr.value.push(item);
          }
        });
      });

      // 然后通过循环获取所有父节点的ParentId并去重
      allParentArr.value.map((item: any) => {
        menuId.value.forEach((childId: string) => {
          if (item.menuId === childId) {
            parentArr.add(item.parentId);
          }
        });
      });

      parentArr.forEach((parentId: any) => {
        parent.value.push(parentId);
      });
      parentId.value = Array.from(parentArr);

      const data = allData.value.find((item: any) => item.menuId === parentObj.parentId);

      const root: any = allData.value.find((item: any) => item.menuId === (data as any)?.parentId);

      if (menuId.value.length > 0) {
        menuId.value = [root.menuId, ...parentId.value, ...menuId.value];
        menuId.value = Array.from(new Set(menuId.value));
      } else {
        menuId.value = [];
      }
    }
  } catch (error) {
    console.error("Error fetching data", error);
  }
};

// 复选框
const child = ref<any[]>([]); // 子节点ID
const parent = ref<any[]>([]); // 父节点ID
const menuId = ref<any[]>([]); // 选中菜单ID
const selectedData = ref<any[]>([]); // 选中的数据
const allParent = ref<any[]>([]); // 所有父节点
const handleCheck = (row: any) => {
  // 处理复选框的选择
  child.value = [];
  parent.value = [];
  if (useRoleData.isEdit) {
    child.value = firstId.value;
  } else {
    child.value = [];
  }
  selectedData.value.push(row);
  selectedData.value.forEach((item: any) => {
    const obj: any = {
      menuName: item.menuName
    };
    for (const key in item) {
      if (Object.prototype.hasOwnProperty.call(item, key)) {
        const el = item[key];
        if (el.checked) {
          roleMap.value.push(el.menuId);
          // 数组去重
          roleMap.value = [...new Set(roleMap.value)];
          child.value.push(el.menuId);
          if (child.value.length > 0) {
            child.value.forEach((childId: any) => {
              obj[key] = {
                checked: roleMap.value.some((item: any) => item === childId),
                menuId: child.value
              };
            });
          }
        } else {
          // 清除child.value中等于row[prop].menuId的元素
          child.value = child.value.filter((item: any) => item !== el.menuId);
        }
      }
    }
  });

  child.value = Array.from(new Set(child.value));

  const allParentInfo: any[] = [];
  allData.value.map((item: any) => {
    child.value.forEach((childId: any) => {
      if (item.menuId === childId) {
        allParentInfo.push(item);
        return allParent.value.push(item);
      }
    });
  });
  // 拿到选中节点的所有父节点
  const parentArr = new Set();
  allParent.value.map((item: any) => {
    child.value.forEach((childId: string) => {
      if (item.menuId === childId) {
        parentArr.add(item.parentId);
      }
    });
  });
  parentArr.forEach((parentId: any) => {
    parent.value.push(parentId);
  });

  // 获取所有的根节点
  const allRoot: any[] = [];
  allData.value.forEach((item: any) => {
    allParentInfo.forEach((v: any) => {
      if (item.menuId === v.parentId) {
        allRoot.push(item.parentId);
      }
    });
  });
  if (child.value.length > 0) {
    menuId.value = [...allRoot, ...parent.value, ...child.value];
    menuId.value = Array.from(new Set(menuId.value));
  } else {
    menuId.value = [];
  }
};

// 保存
const useRoleData = useRoleDataStore();
const formData = ref(); // 表单数据
const allParentArr = ref<any[]>([]); // 所有父节点数组
const parentArr = new Set(); // 父节点集合
const parentId = ref<any[]>([]); // 已选择的父节点ID

//  保存
const saveEvent = async () => {
  // 保存方法
  if (useRoleData.isEdit) {
    formData.value = useRoleData.roleData;
    formData.value.menuIds = menuId.value;
    formData.value.deptIds = [];
    formData.value.deptCheckStrictly = true;
    formData.value.menuCheckStrictly = true;
    const res = await updateRoleApi(formData.value);
    if (res.code === 200) {
      ElMessage.success("修改成功");
      router.back();
    } else {
      ElMessage.error(res.message);
    }
  } else {
    const data = {
      menuIds: menuId.value,
      deptIds: [],
      deptCheckStrictly: true,
      menuCheckStrictly: true,
      roleName: useRoleData.roleData.roleName,
      remark: useRoleData.roleData.remark,
      roleKey: useRoleData.roleData.roleKey,
      roleSort: useRoleData.roleData.roleSort,
      status: useRoleData.roleData.status
    };
    const res = await addRoleApi(data);
    if (res.code === 200) {
      ElMessage.success("保存成功");
      router.back();
    } else {
      ElMessage.error(res.message);
    }
  }
};

// 选中当前页面所有按钮权限
const selectAllEvent = () => {
  // 选择当前全部按钮权限
  const parentData: any = [];
  tableData.value.forEach((item: any) => {
    columns.value.forEach((column: any) => {
      if (item[column.prop]) {
        item[column.prop].checked = true;
        if (item[column.prop].checked) {
          roleMap.value.push(item[column.prop].menuId);
          menuId.value.push(item[column.prop].menuId);
        }
      }
    });
  });

  // 去重
  roleMap.value = [...new Set(roleMap.value)];
  menuId.value = [...new Set(menuId.value)];
  allData.value.forEach((item: any) => {
    menuId.value.forEach((v: any) => {
      if (item.menuId === v) {
        parentData.push(item);
      }
    });
  });
  console.table(parentData);
  const parent: any = [];
  const parentId: any = [];
  allData.value.forEach((item: any) => {
    parentData.find((v: any) => {
      if (item.menuId === v.parentId) {
        parentId.push(item.menuId);
        parent.push(item);
      }
    });
  });
  const rootId: any = [];
  allData.value.find((item: any) => {
    parent.find((v: any) => {
      if (item.menuId === v.parentId) {
        rootId.push(item.menuId);
      }
    });
  });
  menuId.value = [...rootId, ...parentId, ...menuId.value];
  menuId.value = Array.from(new Set(menuId.value));
};

// 获取列表
const tableData = ref<DeptItem[]>([]); // 表格数据
// 列信息
const columns = ref<any>([]); // 列配置
const loading = ref(false); // 加载状态

onMounted(() => {
  // 组件挂载后获取菜单列表和初始化
  getMenuListApi();
  init();
});
</script>

<style lang="scss" scoped>
.app-container {
  width: 100%;
  height: 100%;

  .demo-form-inline .el-select {
    --el-select-width: 220px;
  }

  .button-style {
    margin-bottom: 10px;
  }

  :deep(.el-checkbox__inner) {
    transform: scale(1.4);
  }
}

:deep(.el-tree-node__content) {
  padding: 10px 0 !important;
  height: 100%;
}
</style>
